package edu.cicese.alz.util;

import edu.cicese.alz.swing.SwingUtil;

import java.awt.Color;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.ParseException;
import java.util.Date;
import java.util.Properties;

/**
 * Created by: Eduardo Quintana Contreras
 * Date: 4/06/12
 * Time: 04:41 PM
 */
public class PropertyUtil {

	public final static String HOME_DIR = "homeDirectory";
	public final static String HOME_LATITUDE = "homeLatitude";
	public final static String HOME_LONGITUDE = "homeLongitude";
	public final static String HOME_ZOOM = "homeZoom";

	// Reports
	public final static String REP_USERS_ALL = "repUsersAll";
	public final static String REP_USERS = "repUsers";

	public final static String REP_SHOW_CHARTS = "repShowCharts";
	public final static String REP_SAVE_CHARTS = "repSaveCharts";

	public final static String REP_PERIOD_ALL = "repPeriodAll";
	public final static String REP_PERIOD_FROM = "repPeriodFrom";
	public final static String REP_PERIOD_TO = "repPeriodTo";
	public final static String REP_INTERVAL_FROM = "repIntervalFrom";
	public final static String REP_INTERVAL_TO = "repIntervalTo";

	// Accelerometer report
	public final static String REP_ACC_TYPE = "repAccType";

	public final static String REP_ACC_USERS_ALL = "repAccUsersAll";
	public final static String REP_ACC_USERS = "repAccUsers";

	public final static String REP_ACC_SHOW_CHARTS = "repAccShowCharts";
	public final static String REP_ACC_SAVE_CHARTS = "repAccSaveCharts";

	public final static String REP_ACC_MAGNITUDE_DAY = "repAccMagDay";
	public final static String REP_ACC_MAGNITUDE_FROM = "repAccMagFrom";
	public final static String REP_ACC_MAGNITUDE_TO = "repAccMagTo";

	public final static String REP_ACC_MAGNITUDE_COLOR_MAGNITUDE = "repAccMagColorMagnitude";

	public final static String REP_ACC_INTENSITY_ALL = "repAccIntAll";
	public final static String REP_ACC_INTENSITY_FROM = "repAccIntFrom";
	public final static String REP_ACC_INTENSITY_TO = "repAccIntTo";

	public final static String REP_ACC_INTENSITY_COLOR_NO_DATA = "repAccIntColorNoData";
	public final static String REP_ACC_INTENSITY_COLOR_NO_MOVEMENT = "repAccIntColorNoMovement";
	public final static String REP_ACC_INTENSITY_COLOR_SEDENTARY = "repAccIntColorSedentary";
	public final static String REP_ACC_INTENSITY_COLOR_LIGHT = "repAccIntColorLight";
	public final static String REP_ACC_INTENSITY_COLOR_MODERATE = "repAccIntColorModerate";
	public final static String REP_ACC_INTENSITY_COLOR_HARD = "repAccIntColorHard";

	public final static String REP_ACC_INTENSITY_THRESHOLD_SEDENTARY = "repAccIntThresholdSedentary";
	public final static String REP_ACC_INTENSITY_THRESHOLD_LIGHT = "repAccIntThresholdLight";
	public final static String REP_ACC_INTENSITY_THRESHOLD_MODERATE = "repAccIntThresholdModerate";
	public final static String REP_ACC_INTENSITY_THRESHOLD_HARD = "repAccIntThresholdHard";

	public final static String REP_ACC_ADVANCED_ALPHA = "repAccAdvAlpha";
	public final static String REP_ACC_ADVANCED_EPOCH = "repAccAdvEpoch";
	public final static String REP_ACC_ADVANCED_MINIMUM = "repAccAdvMin";

	// GPS report
	public final static String REP_GPS_TYPE = "repGpsType";

	public final static String REP_GPS_USERS_ALL = "repGpsUsersAll";
	public final static String REP_GPS_USERS = "repGpsUsers";

	public final static String REP_GPS_SHOW_CHARTS = "repGpsShowCharts";
	public final static String REP_GPS_SAVE_CHARTS = "repGpsSaveCharts";

	public final static String REP_GPS_HOME_RADIUS = "repGpsHomeRadius";

	public final static String REP_GPS_PERIOD_ALL = "repGpsPeriodAll";
	public final static String REP_GPS_PERIOD_FROM = "repGpsPeriodFrom";
	public final static String REP_GPS_PERIOD_TO = "repGpsPeriodTo";
	public final static String REP_GPS_INTERVAL_FROM = "repGpsIntervalFrom";
	public final static String REP_GPS_INTERVAL_TO = "repGpsIntervalTo";
	public final static String REP_GPS_DAILY_MAP = "repGpsDailyMap";

	public final static String REP_GPS_MAP_SHOW_MARKERS = "repGpsMapShowMarkers";
	public final static String REP_GPS_MAP_SHOW_TRACKS = "repGpsMapShowTracks";
	public final static String REP_GPS_MAP_SHOW_LABELS = "repGpsMapShowLabels";
	public final static String REP_GPS_MAP_SHOW_LOCATIONS = "repGpsMapShowLocations";
	public final static String REP_GPS_MAP_SHOW_GRID = "repGpsMapShowGrid";
	public final static String REP_GPS_MAP_SHOW_ZOOM_CONTROL = "repGpsMapShowZoomControl";
	public final static String REP_GPS_MAP_SHOW_MARKER_CONTROL = "repGpsMapShowMarkerControl";
	public final static String REP_GPS_MAP_SHOW_LOCATION_INFO = "repGpsMapShowLocationText";

	public final static String REP_GPS_MAP_LAYER = "repGpsMapLayer";

	public final static String REP_GPS_MAP_COLOR_MARKER_BACKGROUND = "repGpsMapColorMarkerBackground";
	public final static String REP_GPS_MAP_COLOR_MARKER_BORDER = "repGpsMapColorMarkerBorder";
	public final static String REP_GPS_MAP_MARKER_OPACITY = "repGpsMapMarkerTransparency";

	public final static String REP_GPS_MAP_COLOR_LOCATION_BACKGROUND = "repGpsMapColorLocationBackground";
	public final static String REP_GPS_MAP_COLOR_LOCATION_BORDER = "repGpsMapColorLocationBorder";
	public final static String REP_GPS_MAP_LOCATION_OPACITY = "repGpsMapLocationTransparency";
	public final static String REP_GPS_MAP_LOCATION_SIZE = "repGpsMapLocationSize";
	public final static String REP_GPS_MAP_LOCATION_INFO_TYPE = "repGpsMapLocationInfoType";
	public final static String REP_GPS_MAP_ADJUST_SIZE = "repGpsMapLocationAdjustSize";

	public final static String REP_GPS_MAP_LOCATION_MIN_TIME = "repGpsMapLocationMinTime";
	public final static String REP_GPS_MAP_LOCATION_RADIUS = "repGpsMapLocationRadius";
	public final static String REP_GPS_MAP_LOCATION_MERGE = "repGpsMapLocationMerge";
	public final static String REP_GPS_MAP_LOCATION_MERGE_RADIUS = "repGpsMapLocationMergeRadius";

	public final static String REP_GPS_MAP_COLOR_TRACK = "repGpsMapColorLine";
	public final static String REP_GPS_MAP_TRACK_THICKNESS = "repGpsMapLineThickness";
	public final static String REP_GPS_MAP_TRACK_OPACITY = "repGpsMapLineTransparency";

	public final static String REP_GPS_MAP_LABEL_SHOW_DAY = "repGpsMapLabelShowDay";
	public final static String REP_GPS_MAP_LABEL_SHOW_HOUR = "repGpsMapLabelShowHour";
	public final static String REP_GPS_MAP_LABEL_SHOW_TIME = "repGpsMapLabelShowTime";
	public final static String REP_GPS_MAP_LABEL_SHOW_DISTANCE = "repGpsMapLabelShowDistance";
	public final static String REP_GPS_MAP_LABEL_SHOW_SPEED = "repGpsMapLabelShowSpeed";

	public final static String REP_GPS_BLOCK_COLOR_NO_DATA = "repGpsBlockColorNoData";
	public final static String REP_GPS_BLOCK_COLOR_HOME = "repGpsBlockColorHome";
	public final static String REP_GPS_BLOCK_COLOR_OUT = "repGpsBlockColorOut";

	// NFC report
	public final static String REP_NFC_TYPE = "repNfcType";
	public final static String REP_NFC_COLOR_NO_DATA = "repNfcColorNoData";
	public final static String REP_NFC_PROFILE = "repNfcProfile";

	// Combined report
	public final static String REP_CMB_HAS_ACC = "repCmbHasAccelerometer";
	public final static String REP_CMB_HAS_GPS = "repCmbHasGps";
	public final static String REP_CMB_HAS_NFC = "repCmbHasNfc";
	public final static String REP_CMB_OPACITY_ACC_NO_DATA = "repCmbOpacityAccNoData";
	public final static String REP_CMB_OPACITY_ACC_GENERAL_OPACITY = "repCmbOpacityAccGeneral";
	public final static String REP_CMB_OPACITY_GPS_NO_DATA = "repCmbOpacityGpsNoData";
	public static final String REP_CMB_OPACITY_GPS_HOME_OPACITY = "repCmbOpacityGpsHome";
	public final static String REP_CMB_OPACITY_GPS_OUT_OPACITY = "repCmbOpacityGpsOut";
	public final static String REP_CMB_OPACITY_NFC_NO_DATA = "repCmbOpacityNfcNoData";
	public final static String REP_CMB_OPACITY_NFC_GENERAL_OPACITY = "repCmbOpacityNfcGeneral";

	// NFC tags
	public final static String NFC_PROFILES = "nfcProfiles";
	public final static String NFC_TAGS = "nfcTags";


	public static Properties getProperties() {
		Properties properties = new Properties();

		try {
			// load the properties file
			properties.load(new FileInputStream(getSettingsPath()));
		} catch (IOException ex) {
			ex.printStackTrace();
		}

		return properties;
	}

	public static void saveProperties(Properties properties) {
		try {
			// save properties to project root folder
			properties.store(new FileOutputStream(getSettingsPath()), null);
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}


	//TODO Check null returns (shouldn't happen)
	public static String getProperty(String property) {
		Properties properties = getProperties();

		if (properties.isEmpty() || !properties.containsKey(property)) {
			System.out.println("Error loading " + property);
			// load default properties
			setDefaultProperties(properties);
		}

		return properties.getProperty(property);
	}


	public static void setProperty(String property, String value) {
		Properties properties = getProperties();
		properties.setProperty(property, value);
		saveProperties(properties);
	}


	public static void setDefaultProperties(Properties properties) {
		if (properties.getProperty(HOME_DIR) == null) {
			properties.setProperty(HOME_DIR, "");
		}
		properties.setProperty(HOME_LATITUDE, "31.861630766802612");
		properties.setProperty(HOME_LONGITUDE, "-116.6028356552124");
		properties.setProperty(HOME_ZOOM, "12");

		setDefaultAccelerometerProperties(properties);
		setDefaultGPSProperties(properties);
//		setDefaultNFCProperties(properties);
		setDefaultCombinedProperties(properties);

		saveProperties(properties);
	}

	public static void setDefaultReportProperties(Properties properties) {
		// Users
		properties.setProperty(REP_USERS_ALL, String.valueOf(false));
		properties.setProperty(REP_USERS, "");

		// Period
		properties.setProperty(REP_PERIOD_ALL, String.valueOf(false));
		properties.setProperty(REP_PERIOD_FROM, "22-11-2011");
		properties.setProperty(REP_PERIOD_TO, "24-11-2011");
		properties.setProperty(REP_INTERVAL_FROM, "00:00:00");
		properties.setProperty(REP_INTERVAL_TO, "24:00:00");

		// Saving options
		properties.setProperty(REP_SHOW_CHARTS, String.valueOf(true));
		properties.setProperty(REP_SAVE_CHARTS, String.valueOf(true));
	}

	public static void setDefaultAccelerometerProperties() {
		Properties properties = getProperties();
		setDefaultAccelerometerProperties(properties);
		saveProperties(properties);
	}

	public static void setDefaultAccelerometerProperties(Properties properties) {
		// Type
		properties.setProperty(REP_ACC_TYPE, "block"); // block or magnitude

		// Users, period, saving options
		setDefaultReportProperties(properties);

		// Advanced options
		properties.setProperty(REP_ACC_ADVANCED_ALPHA, "0.8");

		// INTENSITY
		properties.setProperty(REP_ACC_ADVANCED_EPOCH, "10");
		properties.setProperty(REP_ACC_ADVANCED_MINIMUM, "8");

		// colors
		Color noData = new Color(153, 204, 255);
		Color noMovement = Color.WHITE;
		Color sedentary = Color.WHITE;
		Color light = new Color(153, 255, 51);
		Color moderate = new Color(0, 153, 0);
		Color hard = new Color(255, 102, 0);

		properties.setProperty(REP_ACC_INTENSITY_COLOR_NO_DATA, String.valueOf(noData.getRGB()));
		properties.setProperty(REP_ACC_INTENSITY_COLOR_NO_MOVEMENT, String.valueOf(noMovement.getRGB()));
		properties.setProperty(REP_ACC_INTENSITY_COLOR_SEDENTARY, String.valueOf(sedentary.getRGB()));
		properties.setProperty(REP_ACC_INTENSITY_COLOR_LIGHT, String.valueOf(light.getRGB()));
		properties.setProperty(REP_ACC_INTENSITY_COLOR_MODERATE, String.valueOf(moderate.getRGB()));
		properties.setProperty(REP_ACC_INTENSITY_COLOR_HARD, String.valueOf(hard.getRGB()));

		// activity count thresholds
//		setProperty(REP_ACC_INTENSITY_THRESHOLD_NO_DATA, 0);
//		setProperty(REP_ACC_INTENSITY_THRESHOLD_NO_MOVEMENT, "50");
		properties.setProperty(REP_ACC_INTENSITY_THRESHOLD_SEDENTARY, "50");
		properties.setProperty(REP_ACC_INTENSITY_THRESHOLD_LIGHT, "100");
		properties.setProperty(REP_ACC_INTENSITY_THRESHOLD_MODERATE, "1952");
		properties.setProperty(REP_ACC_INTENSITY_THRESHOLD_HARD, "5724");

		// MAGNITUDE
		Color line = Color.RED;
		properties.setProperty(REP_ACC_MAGNITUDE_COLOR_MAGNITUDE, String.valueOf(line.getRGB()));
	}

	public static void setDefaultGPSProperties() {
		Properties properties = getProperties();
		setDefaultGPSProperties(properties);
		saveProperties(properties);
	}

	public static void setDefaultGPSProperties(Properties properties) {
		// Type
		properties.setProperty(REP_GPS_TYPE, "map"); // block or map

		// Users, period, saving options
		setDefaultReportProperties(properties);
		properties.setProperty(REP_GPS_DAILY_MAP, String.valueOf(true));

		// Advanced options
		properties.setProperty(REP_GPS_HOME_RADIUS, "100");

		// MAP
		properties.setProperty(REP_GPS_MAP_LAYER, "Map"); // Map or Satellite
		properties.setProperty(REP_GPS_MAP_SHOW_MARKERS, String.valueOf(true));
		properties.setProperty(REP_GPS_MAP_SHOW_LOCATIONS, String.valueOf(true));
		properties.setProperty(REP_GPS_MAP_SHOW_TRACKS, String.valueOf(false));
		properties.setProperty(REP_GPS_MAP_SHOW_LABELS, String.valueOf(false));
		properties.setProperty(REP_GPS_MAP_SHOW_GRID, String.valueOf(false));
		properties.setProperty(REP_GPS_MAP_SHOW_ZOOM_CONTROL, String.valueOf(true));
		properties.setProperty(REP_GPS_MAP_SHOW_MARKER_CONTROL, String.valueOf(true));

		// markers
		properties.setProperty(REP_GPS_MAP_COLOR_MARKER_BACKGROUND, String.valueOf(new Color(87, 129, 252).getRGB()));
		properties.setProperty(REP_GPS_MAP_COLOR_MARKER_BORDER, String.valueOf(Color.BLACK.getRGB()));
		properties.setProperty(REP_GPS_MAP_MARKER_OPACITY, "255");

		// locations
		properties.setProperty(REP_GPS_MAP_LOCATION_RADIUS, "50");
		properties.setProperty(REP_GPS_MAP_LOCATION_MIN_TIME, "6");
		properties.setProperty(REP_GPS_MAP_LOCATION_MERGE, String.valueOf(true));
		properties.setProperty(REP_GPS_MAP_LOCATION_MERGE_RADIUS, "50");
		properties.setProperty(REP_GPS_MAP_COLOR_LOCATION_BACKGROUND, String.valueOf(Color.GREEN.getRGB()));
		properties.setProperty(REP_GPS_MAP_COLOR_LOCATION_BORDER, String.valueOf(Color.BLACK.getRGB()));
		properties.setProperty(REP_GPS_MAP_LOCATION_OPACITY, "150");
		properties.setProperty(REP_GPS_MAP_LOCATION_SIZE, "20"); // 1 to 40
		properties.setProperty(REP_GPS_MAP_ADJUST_SIZE, String.valueOf(false));
		properties.setProperty(REP_GPS_MAP_SHOW_LOCATION_INFO, String.valueOf(true));
		properties.setProperty(REP_GPS_MAP_LOCATION_INFO_TYPE, "Incidences"); // Incidences or Time

		// tracks
		properties.setProperty(REP_GPS_MAP_COLOR_TRACK, String.valueOf(Color.RED.getRGB()));
		properties.setProperty(REP_GPS_MAP_TRACK_OPACITY, "100"); // 0 to 255
		properties.setProperty(REP_GPS_MAP_TRACK_THICKNESS, "3"); // 1 to 4

		// labels
		properties.setProperty(REP_GPS_MAP_LABEL_SHOW_DAY, String.valueOf(true));
		properties.setProperty(REP_GPS_MAP_LABEL_SHOW_HOUR, String.valueOf(true));
		properties.setProperty(REP_GPS_MAP_LABEL_SHOW_DISTANCE, String.valueOf(false));
		properties.setProperty(REP_GPS_MAP_LABEL_SHOW_TIME, String.valueOf(false));
		properties.setProperty(REP_GPS_MAP_LABEL_SHOW_SPEED, String.valueOf(false));

		// BLOCK
		properties.setProperty(REP_GPS_BLOCK_COLOR_NO_DATA, String.valueOf(Color.RED.getRGB()));
		properties.setProperty(REP_GPS_BLOCK_COLOR_HOME, String.valueOf(Color.BLUE.getRGB()));
		properties.setProperty(REP_GPS_BLOCK_COLOR_OUT, String.valueOf(Color.GREEN.getRGB()));
	}

	public static void setDefaultNFCProperties() {
		Properties properties = getProperties();
		setDefaultNFCProperties(properties);
		saveProperties(properties);
	}

	public static void setDefaultNFCProperties(Properties properties) {
		properties.setProperty(NFC_TAGS, "");
		properties.setProperty(NFC_PROFILES, "");
		for (String key : properties.stringPropertyNames()) {
			if (key.startsWith("NFC_PROFILE_")) {
				properties.remove(key);
			}
		}

		// Type
		properties.setProperty(REP_NFC_TYPE, "block"); // block or bar

		// Advanced
		properties.setProperty(REP_NFC_PROFILE, "");
		properties.setProperty(REP_NFC_COLOR_NO_DATA, String.valueOf(Color.WHITE.getRGB()));

	}

	public static void setDefaultCombinedProperties() {
		Properties properties = getProperties();
		setDefaultCombinedProperties(properties);
		saveProperties(properties);
	}

	public static void setDefaultCombinedProperties(Properties properties) {
		// Type
		properties.setProperty(REP_CMB_HAS_ACC, String.valueOf(true));
		properties.setProperty(REP_CMB_HAS_GPS, String.valueOf(false));
		properties.setProperty(REP_CMB_HAS_NFC, String.valueOf(true));

		// Users, period, saving options
		setDefaultReportProperties(properties);

		// Advanced
		properties.setProperty(REP_CMB_OPACITY_ACC_NO_DATA, "255");
		properties.setProperty(REP_CMB_OPACITY_ACC_GENERAL_OPACITY, "255");
		properties.setProperty(REP_CMB_OPACITY_GPS_NO_DATA, "0");
		properties.setProperty(REP_CMB_OPACITY_GPS_HOME_OPACITY, "0");
		properties.setProperty(REP_CMB_OPACITY_GPS_OUT_OPACITY, "150");
		properties.setProperty(REP_CMB_OPACITY_NFC_NO_DATA, "0");
		properties.setProperty(REP_CMB_OPACITY_NFC_GENERAL_OPACITY, "255");
	}


	public static String getSettingsPath() {
		String userHome = System.getProperty("user.home");
		if (userHome == null) {
			throw new IllegalStateException("user.home==null");
		}
		File home = new File(userHome);
		File settingsDirectory = new File(home, ".idp");
		if (!settingsDirectory.exists()) {
			if (!settingsDirectory.mkdirs()) {
				throw new IllegalStateException(settingsDirectory.toString());
			}
		}
		return (settingsDirectory + File.separator + "config.properties");
	}

	public static String getIpdDir() {
		return getProperty(HOME_DIR) + Utilities.getSystemSeparator();
	}

	public static String getInfileDir(int userID) {
		return getIpdDir() + "users" + Utilities.getSystemSeparator() + userID + Utilities.getSystemSeparator() + "infiles" + Utilities.getSystemSeparator();
	}

	public static String getReportsDir() {
		return getIpdDir() + "reports" + File.separator;
	}

	public static String getReportChartsDir() {
		return getReportsDir() + "charts" + File.separator;
	}

	public static String getUserDir(int userID) {
		return getIpdDir() + "users" + File.separator + userID + File.separator;
	}

	public static String getAccelerometerCountsDir(int userID) {
		return getUserDir(userID) + "charts" + File.separator + "acc" + File.separator + "counts" + File.separator;
	}

	public static String getUploadedDir(String dsvDir, long timestamp) {
		return dsvDir + "uploaded[" + timestamp + "]" + Utilities.getSystemSeparator();
	}


	public static int getInt(String property) {
		return Integer.valueOf(getProperty(property));
	}

	public static double getDouble(String property) {
		return Double.valueOf(getProperty(property));
	}

	public static boolean getBoolean(String property) {
		return Boolean.valueOf(getProperty(property));
	}

	public static Color getColor(String property) {
		return new Color(Integer.valueOf(getProperty(property)));
	}

	public static Date getDate(String property) {
		try {
			return SwingUtil.calendarDateFormat.parse(getProperty(property));
		} catch (ParseException e) {
			return null;
		}
	}


	public static void removeNFCProfile(String profile) {
		Properties properties = getProperties();
		properties.remove(profile);
		saveProperties(properties);
	}

}
